﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.SessionState;

using Newtonsoft.Json;
using RaceList.activity.help;
using RaceList.activity.util;

namespace RaceList.activity.mhalloween
{
    /// <summary>
    ///     _response.End();  //在Handler中强制终结request请求，会抛出异常
    ///     用户点击跑动，然后触发这个类，对Session中操作，将数据累加
    /// </summary>
    public class Relaying : IHttpHandler, IRequiresSessionState, IAuthWeixin
    {
        public void ProcessRequest(HttpContext context)
        {
            Init(context);
            lock (_obj)
            {
                if (_request["m"] == "add")
                {
                    var score = (double)0;
                    double.TryParse(_request["s"], out score);
                    SessionHelp.UserChengji.ClientScores.Add(score); //如果顺序是固定的，那就可以对比之前在game中生成的集合了
                    return;
                }
                AddScore();
            }
        }

        /// <summary>
        ///     有大神说他不起作用，那就随便吧
        ///     获取一个值，该值指示其他请求是否可以使用 IHttpHandler 实例
        ///     如果 IHttpHandler 实例可再次使用,则为 true;否则为 false
        /// </summary>
        public bool IsReusable
        {
            get { return false; }
        }

        /// <summary>
        ///     将成绩更新到session中
        /// </summary>
        private void AddScore()
        {
            try
            {
                CallTimeOut();
            }
            catch (Exception ex)
            {
                SessionHelp.UserChengji.Dispose();
                WriteToClient(new ErrorMessage
                {
                    Status = Status.Error,
                    Exception = ex.Message,
                    IsShowException = true, //如果是本地访问显示错误
                });
            }
        }

        private void Init(HttpContext context)
        {
            _context = context;
            _request = _context.Request;
            _response = _context.Response;
            _session = context.Session;
        }

        /// <summary>
        ///     向浏览器输出内容
        /// </summary>
        /// <param name="message"></param>
        public void WriteToClient(ErrorMessage message)
        {
            _response.Write(JsonConvert.SerializeObject(message));
        }

        #region field

        private readonly object _obj = new object();
        protected HttpContext _context;
        protected HttpRequest _request;
        protected HttpResponse _response;
        protected HttpSessionState _session;

        #endregion

        #region 需要干些操作

        public void InitRequestQuerystring()
        {
            //参数的组成 clicknum和一段连续成绩的片段，都分别包裹在前面5个随机字符串和后面5个随机字符串

            int num = 0;
            string f = _request["f"];
            string[] strs = f.Split('|');

            int.TryParse(CleanStr(strs[0]), out num);
            var fragment = CleanStr(strs[1]);

            UserChengji userChengji = SessionHelp.UserChengji;
            userChengji.ClickNum = num;
            userChengji.ScoresFragment = fragment;
            SessionHelp.UserChengji = userChengji;
        }

        private string CleanStr(string str)
        {
            //先删除前5个字符
            str = str.Substring(5);
            //再删除后5个字符
            str = str.Substring(0, str.Length - 5);
            return str;
        }

        public void CallTimeOut()
        {
            lock (_obj)
            {
                Thread.Sleep(new Random().Next(1, 500));
                if (IsSessionValid()) //只有session校验通过后，才进行一些其他的操作
                {
                    #region 如果不能添加到数据库,跳转到result页
                    if (!IsDbValid()) //只有存在RelayId的时候检查字表的数量
                    {
                        int relayId = SessionHelp.UserChengji.RelayId;
                        SessionHelp.UserChengji.Dispose();
                        var message = new ErrorMessage
                        {
                            Finished = true,
                            Score = 0,
                            Status = Status.Error,
                            Exception = "手慢了0.01s，看看是谁抢先完成了帮帮跑！",
                            IsShowException = true,
                        };
                        if (relayId != 0)
                        {
                            message.Url = "Relayresult.aspx?" + Parameters.relay + "=" + relayId;
                        }
                        else
                        {
                            message.Url = SessionHelp.IndexUrl;
                        }

                        WriteToClient(message);
                        return;
                    }
                    #endregion

                    #region 如果需要修改或添加数据
                    InitRequestQuerystring();


                    #region 成功添加数据，跳转result页
                    if (CheckData())
                    {
                        if (!SessionHelp.UserChengji.IsAddedToDb) //没有添加过数据库中
                        {
                            var score = SessionHelp.UserChengji.Score;
                            int relayId = AddDb(); //添加到数据                        
                            SessionHelp.UserChengji.Dispose(); //清除session中的成绩
                            WriteToClient(new ErrorMessage
                            {
                                Score = score,
                                Finished = true,
                                //添加一个score参数用于显示成绩
                                Url = ("Relayresult.aspx?" + Parameters.relay + "=" + relayId + "&score=" + score).AddTimeStamp(),
                            });
                        }
                        return;
                    }
                    #endregion
                    #region 如果数据校验失败 或者已经添加到数据库的话，session中成绩信息都清除了，所以最好是让他返回首页
                    WriteToClient(new ErrorMessage
                    {
                        Status = Status.Error,
                        Exception = "游戏过程不安全，请稍后重试",
                        IsShowException = true,
                        Score = 0,
                        Finished = true,
                        Url = SessionHelp.IndexUrl
                    });
                    #endregion

                    #endregion
                }
                else
                {
                    SessionHelp.UserChengji.Dispose();
                    WriteToClient(new ErrorMessage
                    {
                        Status = Status.Error,
                        Exception = "你没有登陆，请稍后重试",
                        IsShowException = true,
                        Finished = true,
                        Url = SessionHelp.IndexUrl
                    });
                }
            }
        }
        /// <summary>
        /// 校验数据
        /// </summary>
        private bool CheckData()
        {
            var result = false;
            var userChengji = SessionHelp.UserChengji;
            //根据返回的步数得到计算游戏成绩
            var score = GetScore(userChengji.Scores, userChengji.ClickNum);

            userChengji.Score = score;

            var scoreString = GetScoreString(userChengji.Scores);
            if (scoreString.Contains(userChengji.ScoresFragment.Substring(0,7)))
                result = true;

            return result;
        }

        private double GetScore(List<double> source, int clicknum)
        {
            var result = (double)0;
            int count = source.Count;
            if (clicknum > count)
            {
                var num = clicknum / count;  //120/100=1
                result += source.Sum() * num;
                clicknum = clicknum % count;//120%100=20
            }
            for (int i = 0; i < clicknum; i++)
            {
                result += source[i];
            }
            return result;
        }

        private string GetScoreString(List<double> source)
        {
            var result = "";
            foreach (var item in source)
            {
                result += item;
            }
            result += result;
            result += result;
            result += result;
            return result;
        }

        /// <summary>
        ///     校验Activity_SubRelay中的数据条目,如果操作配置的值则返回false
        /// </summary>
        /// <returns></returns>
        private bool IsDbValid()
        {
            UserChengji userChengji = SessionHelp.UserChengji;
            if (userChengji.RelayId != 0)
            {
                if (RelayQuery.GetSubRelayList(userChengji.RelayId).Count + 1 >= ActivityConfig.MHalloweenTotalPerson)
                {
                    return false;
                }
            }
            return true;
        }

        private int AddDb()
        {
            UserChengji userChengji = SessionHelp.UserChengji;
            UserData userData = SessionHelp.UserData;

            try
            {
                if (userChengji.IsHelp) //根据IsHelp选择插入到那个数据库中
                {
                    var subrelay = new Activity_SubRelay
                    {
                        AddTime = DateTime.Now,
                        ClickNum = userChengji.ClickNum,
                        RelayId = userChengji.RelayId,
                        Score = userChengji.Score,
                        WeixinUserId = userData.WeixinUserId,
                    };
                    RelayQuery.AddSubRelay(subrelay);
                    return userChengji.RelayId;
                }
                else
                {
                    ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
                    var relay = db.Activity_Relay.FirstOrDefault(s => s.Id == SessionHelp.UserChengji.FirstAddRelayId);
                    relay.AddTime = DateTime.Now;
                    relay.ClickNum = userChengji.ClickNum;
                    relay.Score = userChengji.Score;
                    relay.SumScore = userChengji.Score;
                    relay.WeixinUserId = userData.WeixinUserId;
                    relay.CycleId = SessionHelp.CycleId;
                    relay.EditTime = DateTime.Now;
                    db.SubmitChanges();  //封装这个真的有意义了吗？

                    return relay.Id;
                }
            }
            finally //不论失败与否，都是添加成功，然后第二次不能再添加
            {
                userChengji.IsAddedToDb = true;
            }
        }

        /// <summary>
        ///     只要检查Session中的UserData，CycleId！=0
        ///     判断session中数据是否符合要求
        ///     用于在计时器中添加到数据库之前的校验
        /// </summary>
        private bool IsSessionValid()
        {
            if (_context.Session != null)
            {
                return SessionHelp.CycleId != 0 && SessionHelp.ValidUserData();
            }
            return false;
        }

        #endregion
    }
}